#include "simodo/lsp-client/Location.h"

#include "simodo/inout/convert/functions.h"

namespace simodo::lsp
{
    bool parsePosition(const variable::Value & position_value, inout::Position & position)
    {
        if (position_value.type() != variable::ValueType::Object)
            return false;

        const variable::Value & line_value      = position_value.getObject()->find(u"line");
        const variable::Value & character_value = position_value.getObject()->find(u"character");

        if (line_value.type() != variable::ValueType::Int
        || character_value.type() != variable::ValueType::Int)
            return false;

        position = inout::Position(line_value.getInt(), character_value.getInt());

        return true;
    }

    bool parseRange(const variable::Value & range_value, inout::Range & range)
    {
        if (range_value.type() != variable::ValueType::Object) 
            return false;

        inout::Position start, end;

        std::shared_ptr<variable::Object> range_object = range_value.getObject();
        if (!parsePosition(range_object->find(u"start"), start)
        || !parsePosition(range_object->find(u"end"), end))
            return false;

        range = inout::Range(start, end);

        return true;
    }

    bool parseLocation(const variable::Value & location_value, inout::Location & location)
    {
        if (location_value.type() != variable::ValueType::Object) 
            return false;

        std::shared_ptr<variable::Object> location_object = location_value.getObject();
        const variable::Value &           uri_value     = location_object->find(u"uri");
        if (uri_value.type() != variable::ValueType::String)
            return false;

        inout::Range range;

        if (!parseRange(location_object->find(u"range"), range))
            return false;

        location = inout::Location(inout::toU8(uri_value.getString()), range);

        return true;
    }

}
